//! 配置管理模块
//! 
//! 这个模块负责应用程序的配置管理，包括：
//! - 从环境变量和配置文件加载配置
//! - 配置验证和默认值设置
//! - 不同环境的配置支持

use serde::{Deserialize, Serialize};

/// 应用程序主配置
/// 
/// 包含所有子系统的配置信息
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AppConfig {
    pub server: ServerConfig,
    pub database: DatabaseConfig,
    pub redis: RedisConfig,
    pub jwt: JwtConfig,
    pub websocket: WebSocketConfig,
    pub tcp: TcpConfig,
    pub monitoring: MonitoringConfig,
}

/// 服务器配置
/// 
/// HTTP服务器的相关配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ServerConfig {
    pub host: String,
    pub port: u16,
    pub workers: Option<usize>,
}

impl Default for ServerConfig {
    fn default() -> Self {
        Self {
            host: "127.0.0.1".to_string(),
            port: 3000,
            workers: None,
        }
    }
}

/// 数据库配置
/// 
/// PostgreSQL数据库连接配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DatabaseConfig {
    pub url: String,
    pub max_connections: u32,
    pub min_connections: u32,
    pub acquire_timeout: u64,
    pub idle_timeout: u64,
    pub max_lifetime: u64,
    pub connect_timeout: u64,
}

impl Default for DatabaseConfig {
    fn default() -> Self {
        Self {
            url: "postgresql://postgres:password@localhost:5432/rust_web_service_demo".to_string(),
            max_connections: 20,
            min_connections: 5,
            acquire_timeout: 30,
            idle_timeout: 600,
            max_lifetime: 1800,
            connect_timeout: 10,
        }
    }
}

/// Redis配置
/// 
/// Redis缓存服务器配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RedisConfig {
    pub url: String,
    pub max_connections: u32,
    pub connection_timeout: u64,
    pub command_timeout: u64,
}

impl Default for RedisConfig {
    fn default() -> Self {
        Self {
            url: "redis://localhost:6379".to_string(),
            max_connections: 10,
            connection_timeout: 5,
            command_timeout: 3,
        }
    }
}

/// JWT配置
/// 
/// JSON Web Token相关配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct JwtConfig {
    pub secret: String,
    pub expiration_days: u64,
    pub issuer: String,
    pub audience: String,
}

impl Default for JwtConfig {
    fn default() -> Self {
        Self {
            secret: "your-super-secret-jwt-key-change-this-in-production".to_string(),
            expiration_days: 7,
            issuer: "rust-web-service-demo".to_string(),
            audience: "rust-web-service-demo-users".to_string(),
        }
    }
}

/// WebSocket配置
/// 
/// WebSocket服务器配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WebSocketConfig {
    pub port: u16,
    pub max_connections: usize,
    pub heartbeat_interval: u64,
}

impl Default for WebSocketConfig {
    fn default() -> Self {
        Self {
            port: 3001,
            max_connections: 1000,
            heartbeat_interval: 30,
        }
    }
}

/// TCP配置
/// 
/// TCP服务器配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TcpConfig {
    pub port: u16,
    pub max_connections: usize,
    pub buffer_size: usize,
}

impl Default for TcpConfig {
    fn default() -> Self {
        Self {
            port: 3002,
            max_connections: 1000,
            buffer_size: 4096,
        }
    }
}

/// 监控配置
/// 
/// 监控和指标收集配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MonitoringConfig {
    pub port: u16,
    pub enable_metrics: bool,
    pub enable_health_check: bool,
}

impl Default for MonitoringConfig {
    fn default() -> Self {
        Self {
            port: 9090,
            enable_metrics: true,
            enable_health_check: true,
        }
    }
}

impl AppConfig {
    /// 加载应用程序配置
    /// 
    /// 从多个来源加载配置：
    /// 1. 默认配置
    /// 2. 配置文件（config/default.toml, config/production.toml等）
    /// 3. 环境变量
    /// 
    /// # 返回值
    /// - `Result<Self, config::ConfigError>`: 加载成功返回配置，失败返回错误
    pub fn load() -> Result<Self, config::ConfigError> {
        // 获取运行环境
        let run_mode = std::env::var("RUN_MODE").unwrap_or_else(|_| "development".into());
        
        let settings = config::Config::builder()
            // 默认配置
            .add_source(config::File::with_name("config/default").required(false))
            // 环境特定配置
            .add_source(config::File::with_name(&format!("config/{}", run_mode)).required(false))
            // 本地配置（不提交到版本控制）
            .add_source(config::File::with_name("config/local").required(false))
            // 环境变量覆盖（使用APP_前缀）
            .add_source(config::Environment::with_prefix("APP").separator("__"))
            // 直接环境变量（使用下划线分隔）
            .add_source(config::Environment::with_prefix("APP").separator("_"))
            .build()?;

        let app_config: AppConfig = settings.try_deserialize()?;
        
        // 验证配置
        app_config.validate()?;
        
        tracing::info!("📋 配置加载完成，运行模式: {}", run_mode);
        Ok(app_config)
    }

    /// 验证配置的有效性
    /// 
    /// 检查配置中的关键参数是否有效
    /// 
    /// # 返回值
    /// - `Result<(), config::ConfigError>`: 验证成功返回Ok，失败返回错误
    pub fn validate(&self) -> Result<(), config::ConfigError> {
        // 验证服务器配置
        if self.server.port == 0 {
            return Err(config::ConfigError::Message("服务器端口不能为0".to_string()));
        }

        // 验证数据库配置
        if self.database.max_connections == 0 {
            return Err(config::ConfigError::Message("数据库最大连接数不能为0".to_string()));
        }

        if self.database.url.is_empty() {
            return Err(config::ConfigError::Message("数据库URL不能为空".to_string()));
        }

        // 验证Redis配置
        if self.redis.url.is_empty() {
            return Err(config::ConfigError::Message("Redis URL不能为空".to_string()));
        }

        // 验证JWT配置
        if self.jwt.secret.len() < 32 {
            return Err(config::ConfigError::Message("JWT密钥长度至少32个字符".to_string()));
        }

        if self.jwt.secret == "your-super-secret-jwt-key-change-this-in-production" {
            tracing::warn!("⚠️ 您正在使用默认的JWT密钥，生产环境请更换！");
        }

        // 验证WebSocket配置
        if self.websocket.port == 0 {
            return Err(config::ConfigError::Message("WebSocket端口不能为0".to_string()));
        }

        // 验证TCP配置
        if self.tcp.port == 0 {
            return Err(config::ConfigError::Message("TCP端口不能为0".to_string()));
        }

        tracing::info!("✅ 配置验证通过");
        Ok(())
    }

    /// 获取数据库连接池配置
    /// 
    /// 返回SQLx连接池的配置选项
    pub fn database_pool_options(&self) -> sqlx::postgres::PgPoolOptions {
        sqlx::postgres::PgPoolOptions::new()
            .max_connections(self.database.max_connections)
            .min_connections(self.database.min_connections)
            .acquire_timeout(std::time::Duration::from_secs(self.database.acquire_timeout))
            .idle_timeout(Some(std::time::Duration::from_secs(self.database.idle_timeout)))
            .max_lifetime(Some(std::time::Duration::from_secs(self.database.max_lifetime)))
            .test_before_acquire(false)
    }

    /// 获取Redis连接池配置
    /// 
    /// 返回Redis连接池的配置选项
    pub fn redis_pool_config(&self) -> deadpool_redis::Config {
        deadpool_redis::Config::from_url(&self.redis.url)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_default_config() {
        let config = AppConfig {
            server: ServerConfig::default(),
            database: DatabaseConfig::default(),
            redis: RedisConfig::default(),
            jwt: JwtConfig::default(),
            websocket: WebSocketConfig::default(),
            tcp: TcpConfig::default(),
            monitoring: MonitoringConfig::default(),
        };

        assert_eq!(config.server.port, 3000);
        assert_eq!(config.database.max_connections, 20);
        assert_eq!(config.redis.max_connections, 10);
        assert_eq!(config.jwt.expiration_days, 7);
        assert_eq!(config.websocket.port, 3001);
        assert_eq!(config.tcp.port, 3002);
        assert_eq!(config.monitoring.port, 9090);
    }

    #[test]
    fn test_config_validation() {
        let mut config = AppConfig {
            server: ServerConfig {
                port: 0, // 无效端口
                ..Default::default()
            },
            database: DatabaseConfig::default(),
            redis: RedisConfig::default(),
            jwt: JwtConfig::default(),
            websocket: WebSocketConfig::default(),
            tcp: TcpConfig::default(),
            monitoring: MonitoringConfig::default(),
        };

        assert!(config.validate().is_err());

        config.server.port = 3000;
        assert!(config.validate().is_ok());
    }
}
